Adapt System.BitConverter to handle big endian (network) byte ordering in order to create number types from bytes and vice-versa


/ Published in: C#
Save to your folder(s)

The System.BitConverter class allows you to convert between bytes (in an array) and numerical types (int, uint, etc). However, it doesn't seem to let you set the endianness (which byte is most significant, e.g. in an int/Int32, there are four bytes, so which way do you read them?). It seems to operate such that the methods always return values appropriate to little endian (host order) systems (most significant byte is on the right). Since, in embedded systems, it is often necessary to interact with big-endian systems, I created this class to provide the functionality for either endianness. You simply set the endianness in the class, then all methods will return endian-aware values.

Please let me know if there is a better solution out there, as I searched a lot before deciding to do it this way. (Note: Instead of using LINQ [e.g. myArray.Reverse().ToArray()], you can use Array.Reverse(myArray).)

Found a bug in the previous code in that the arrays were being reversed, but the starting index was not, resulting in non-obvious behavior. I fixed that for all but the ToString methods.


Copy this code and paste it in your HTML
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5.  
  6. namespace Utils
  7. {
  8. /// <summary>
  9. /// Converts base data types to an array of bytes, and an array of bytes to base
  10. /// data types.
  11. /// All info taken from the meta data of System.BitConverter. This implementation
  12. /// allows for Endianness consideration.
  13. ///</summary>
  14. public static class BitConverter
  15. {
  16. /// <summary>
  17. /// Indicates the byte order ("endianess") in which data is stored in this computer
  18. /// architecture.
  19. ///</summary>
  20. public static bool IsLittleEndian { get; set; } // should default to false, which is what we want for Empire
  21.  
  22. /// <summary>
  23. /// Converts the specified double-precision floating point number to a 64-bit
  24. /// signed integer.
  25. ///
  26. /// Parameters:
  27. /// value:
  28. /// The number to convert.
  29. ///
  30. /// Returns:
  31. /// A 64-bit signed integer whose value is equivalent to value.
  32. ///</summary>
  33. public static long DoubleToInt64Bits(double value) { throw new NotImplementedException(); }
  34. ///
  35. /// <summary>
  36. /// Returns the specified Boolean value as an array of bytes.
  37. ///
  38. /// Parameters:
  39. /// value:
  40. /// A Boolean value.
  41. ///
  42. /// Returns:
  43. /// An array of bytes with length 1.
  44. ///</summary>
  45. public static byte[] GetBytes(bool value)
  46. {
  47. if (IsLittleEndian)
  48. {
  49. return System.BitConverter.GetBytes(value);
  50. }
  51. else
  52. {
  53. return System.BitConverter.GetBytes(value).Reverse().ToArray();
  54. }
  55. }
  56. ///
  57. /// <summary>
  58. /// Returns the specified Unicode character value as an array of bytes.
  59. ///
  60. /// Parameters:
  61. /// value:
  62. /// A character to convert.
  63. ///
  64. /// Returns:
  65. /// An array of bytes with length 2.
  66. ///</summary>
  67. public static byte[] GetBytes(char value)
  68. {
  69. if (IsLittleEndian)
  70. {
  71. return System.BitConverter.GetBytes(value);
  72. }
  73. else
  74. {
  75. return System.BitConverter.GetBytes(value).Reverse().ToArray();
  76. }
  77. }
  78. ///
  79. /// <summary>
  80. /// Returns the specified double-precision floating point value as an array of
  81. /// bytes.
  82. ///
  83. /// Parameters:
  84. /// value:
  85. /// The number to convert.
  86. ///
  87. /// Returns:
  88. /// An array of bytes with length 8.
  89. ///</summary>
  90. public static byte[] GetBytes(double value)
  91. {
  92. if (IsLittleEndian)
  93. {
  94. return System.BitConverter.GetBytes(value);
  95. }
  96. else
  97. {
  98. return System.BitConverter.GetBytes(value).Reverse().ToArray();
  99. }
  100. }
  101. ///
  102. /// <summary>
  103. /// Returns the specified single-precision floating point value as an array of
  104. /// bytes.
  105. ///
  106. /// Parameters:
  107. /// value:
  108. /// The number to convert.
  109. ///
  110. /// Returns:
  111. /// An array of bytes with length 4.
  112. ///</summary>
  113. public static byte[] GetBytes(float value)
  114. {
  115. if (IsLittleEndian)
  116. {
  117. return System.BitConverter.GetBytes(value);
  118. }
  119. else
  120. {
  121. return System.BitConverter.GetBytes(value).Reverse().ToArray();
  122. }
  123. }
  124. ///
  125. /// <summary>
  126. /// Returns the specified 32-bit signed integer value as an array of bytes.
  127. ///
  128. /// Parameters:
  129. /// value:
  130. /// The number to convert.
  131. ///
  132. /// Returns:
  133. /// An array of bytes with length 4.
  134. ///</summary>
  135. public static byte[] GetBytes(int value)
  136. {
  137. if (IsLittleEndian)
  138. {
  139. return System.BitConverter.GetBytes(value);
  140. }
  141. else
  142. {
  143. return System.BitConverter.GetBytes(value).Reverse().ToArray();
  144. }
  145. }
  146. ///
  147. /// <summary>
  148. /// Returns the specified 64-bit signed integer value as an array of bytes.
  149. ///
  150. /// Parameters:
  151. /// value:
  152. /// The number to convert.
  153. ///
  154. /// Returns:
  155. /// An array of bytes with length 8.
  156. ///</summary>
  157. public static byte[] GetBytes(long value)
  158. {
  159. if (IsLittleEndian)
  160. {
  161. return System.BitConverter.GetBytes(value);
  162. }
  163. else
  164. {
  165. return System.BitConverter.GetBytes(value).Reverse().ToArray();
  166. }
  167. }
  168. ///
  169. /// <summary>
  170. /// Returns the specified 16-bit signed integer value as an array of bytes.
  171. ///
  172. /// Parameters:
  173. /// value:
  174. /// The number to convert.
  175. ///
  176. /// Returns:
  177. /// An array of bytes with length 2.
  178. ///</summary>
  179. public static byte[] GetBytes(short value)
  180. {
  181. if (IsLittleEndian)
  182. {
  183. return System.BitConverter.GetBytes(value);
  184. }
  185. else
  186. {
  187. return System.BitConverter.GetBytes(value).Reverse().ToArray();
  188. }
  189. }
  190. ///
  191. /// <summary>
  192. /// Returns the specified 32-bit unsigned integer value as an array of bytes.
  193. ///
  194. /// Parameters:
  195. /// value:
  196. /// The number to convert.
  197. ///
  198. /// Returns:
  199. /// An array of bytes with length 4.
  200. ///</summary>
  201. [CLSCompliant(false)]
  202. public static byte[] GetBytes(uint value)
  203. {
  204. if (IsLittleEndian)
  205. {
  206. return System.BitConverter.GetBytes(value);
  207. }
  208. else
  209. {
  210. return System.BitConverter.GetBytes(value).Reverse().ToArray();
  211. }
  212. }
  213. ///
  214. /// <summary>
  215. /// Returns the specified 64-bit unsigned integer value as an array of bytes.
  216. ///
  217. /// Parameters:
  218. /// value:
  219. /// The number to convert.
  220. ///
  221. /// Returns:
  222. /// An array of bytes with length 8.
  223. ///</summary>
  224. [CLSCompliant(false)]
  225. public static byte[] GetBytes(ulong value)
  226. {
  227. if (IsLittleEndian)
  228. {
  229. return System.BitConverter.GetBytes(value);
  230. }
  231. else
  232. {
  233. return System.BitConverter.GetBytes(value).Reverse().ToArray();
  234. }
  235. }
  236. ///
  237. /// <summary>
  238. /// Returns the specified 16-bit unsigned integer value as an array of bytes.
  239. ///
  240. /// Parameters:
  241. /// value:
  242. /// The number to convert.
  243. ///
  244. /// Returns:
  245. /// An array of bytes with length 2.
  246. ///</summary>
  247. public static byte[] GetBytes(ushort value)
  248. {
  249. if (IsLittleEndian)
  250. {
  251. return System.BitConverter.GetBytes(value);
  252. }
  253. else
  254. {
  255. return System.BitConverter.GetBytes(value).Reverse().ToArray();
  256. }
  257. }
  258. ///
  259. /// <summary>
  260. /// Converts the specified 64-bit signed integer to a double-precision floating
  261. /// point number.
  262. ///
  263. /// Parameters:
  264. /// value:
  265. /// The number to convert.
  266. ///
  267. /// Returns:
  268. /// A double-precision floating point number whose value is equivalent to value.
  269. ///</summary>
  270. public static double Int64BitsToDouble(long value) { throw new NotImplementedException(); }
  271. ///
  272. /// <summary>
  273. /// Returns a Boolean value converted from one byte at a specified position in
  274. /// a byte array.
  275. ///
  276. /// Parameters:
  277. /// value:
  278. /// An array of bytes.
  279. ///
  280. /// startIndex:
  281. /// The starting position within value.
  282. ///
  283. /// Returns:
  284. /// true if the byte at startIndex in value is nonzero; otherwise, false.
  285. ///
  286. /// Exceptions:
  287. /// System.ArgumentNullException:
  288. /// value is null.
  289. ///
  290. /// System.ArgumentOutOfRangeException:
  291. /// startIndex is less than zero or greater than the length of value minus 1.
  292. ///</summary>
  293. public static bool ToBoolean(byte[] value, int startIndex) { throw new NotImplementedException(); }
  294. ///
  295. /// <summary>
  296. /// Returns a Unicode character converted from two bytes at a specified position
  297. /// in a byte array.
  298. ///
  299. /// Parameters:
  300. /// value:
  301. /// An array.
  302. ///
  303. /// startIndex:
  304. /// The starting position within value.
  305. ///
  306. /// Returns:
  307. /// A character formed by two bytes beginning at startIndex.
  308. ///
  309. /// Exceptions:
  310. /// System.ArgumentException:
  311. /// startIndex equals the length of value minus 1.
  312. ///
  313. /// System.ArgumentNullException:
  314. /// value is null.
  315. ///
  316. /// System.ArgumentOutOfRangeException:
  317. /// startIndex is less than zero or greater than the length of value minus 1.
  318. ///</summary>
  319. public static char ToChar(byte[] value, int startIndex) { throw new NotImplementedException(); }
  320. ///
  321. /// <summary>
  322. /// Returns a double-precision floating point number converted from eight bytes
  323. /// at a specified position in a byte array.
  324. ///
  325. /// Parameters:
  326. /// value:
  327. /// An array of bytes.
  328. ///
  329. /// startIndex:
  330. /// The starting position within value.
  331. ///
  332. /// Returns:
  333. /// A double precision floating point number formed by eight bytes beginning
  334. /// at startIndex.
  335. ///
  336. /// Exceptions:
  337. /// System.ArgumentException:
  338. /// startIndex is greater than or equal to the length of value minus 7, and is
  339. /// less than or equal to the length of value minus 1.
  340. ///
  341. /// System.ArgumentNullException:
  342. /// value is null.
  343. ///
  344. /// System.ArgumentOutOfRangeException:
  345. /// startIndex is less than zero or greater than the length of value minus 1.
  346. ///</summary>
  347. public static double ToDouble(byte[] value, int startIndex) { throw new NotImplementedException(); }
  348. ///
  349. /// <summary>
  350. /// Returns a 16-bit signed integer converted from two bytes at a specified position
  351. /// in a byte array.
  352. ///
  353. /// Parameters:
  354. /// value:
  355. /// An array of bytes.
  356. ///
  357. /// startIndex:
  358. /// The starting position within value.
  359. ///
  360. /// Returns:
  361. /// A 16-bit signed integer formed by two bytes beginning at startIndex.
  362. ///
  363. /// Exceptions:
  364. /// System.ArgumentException:
  365. /// startIndex equals the length of value minus 1.
  366. ///
  367. /// System.ArgumentNullException:
  368. /// value is null.
  369. ///
  370. /// System.ArgumentOutOfRangeException:
  371. /// startIndex is less than zero or greater than the length of value minus 1.
  372. ///</summary>
  373. public static short ToInt16(byte[] value, int startIndex)
  374. {
  375. if (IsLittleEndian)
  376. {
  377. return System.BitConverter.ToInt16(value, startIndex);
  378. }
  379. else
  380. {
  381. return System.BitConverter.ToInt16(value.Reverse().ToArray(), value.Length - sizeof(Int16) - startIndex);
  382. }
  383. }
  384. ///
  385. /// <summary>
  386. /// Returns a 32-bit signed integer converted from four bytes at a specified
  387. /// position in a byte array.
  388. ///
  389. /// Parameters:
  390. /// value:
  391. /// An array of bytes.
  392. ///
  393. /// startIndex:
  394. /// The starting position within value.
  395. ///
  396. /// Returns:
  397. /// A 32-bit signed integer formed by four bytes beginning at startIndex.
  398. ///
  399. /// Exceptions:
  400. /// System.ArgumentException:
  401. /// startIndex is greater than or equal to the length of value minus 3, and is
  402. /// less than or equal to the length of value minus 1.
  403. ///
  404. /// System.ArgumentNullException:
  405. /// value is null.
  406. ///
  407. /// System.ArgumentOutOfRangeException:
  408. /// startIndex is less than zero or greater than the length of value minus 1.
  409. ///</summary>
  410. public static int ToInt32(byte[] value, int startIndex)
  411. {
  412. if (IsLittleEndian)
  413. {
  414. return System.BitConverter.ToInt32(value, startIndex);
  415. }
  416. else
  417. {
  418. return System.BitConverter.ToInt32(value.Reverse().ToArray(), value.Length - sizeof(Int32) - startIndex);
  419. }
  420. }
  421. ///
  422. /// <summary>
  423. /// Returns a 64-bit signed integer converted from eight bytes at a specified
  424. /// position in a byte array.
  425. ///
  426. /// Parameters:
  427. /// value:
  428. /// An array of bytes.
  429. ///
  430. /// startIndex:
  431. /// The starting position within value.
  432. ///
  433. /// Returns:
  434. /// A 64-bit signed integer formed by eight bytes beginning at startIndex.
  435. ///
  436. /// Exceptions:
  437. /// System.ArgumentException:
  438. /// startIndex is greater than or equal to the length of value minus 7, and is
  439. /// less than or equal to the length of value minus 1.
  440. ///
  441. /// System.ArgumentNullException:
  442. /// value is null.
  443. ///
  444. /// System.ArgumentOutOfRangeException:
  445. /// startIndex is less than zero or greater than the length of value minus 1.
  446. ///</summary>
  447. public static long ToInt64(byte[] value, int startIndex)
  448. {
  449. if (IsLittleEndian)
  450. {
  451. return System.BitConverter.ToInt64(value, startIndex);
  452. }
  453. else
  454. {
  455. return System.BitConverter.ToInt64(value.Reverse().ToArray(), value.Length - sizeof(Int64) - startIndex);
  456. }
  457. }
  458. ///
  459. /// <summary>
  460. /// Returns a single-precision floating point number converted from four bytes
  461. /// at a specified position in a byte array.
  462. ///
  463. /// Parameters:
  464. /// value:
  465. /// An array of bytes.
  466. ///
  467. /// startIndex:
  468. /// The starting position within value.
  469. ///
  470. /// Returns:
  471. /// A single-precision floating point number formed by four bytes beginning at
  472. /// startIndex.
  473. ///
  474. /// Exceptions:
  475. /// System.ArgumentException:
  476. /// startIndex is greater than or equal to the length of value minus 3, and is
  477. /// less than or equal to the length of value minus 1.
  478. ///
  479. /// System.ArgumentNullException:
  480. /// value is null.
  481. ///
  482. /// System.ArgumentOutOfRangeException:
  483. /// startIndex is less than zero or greater than the length of value minus 1.
  484. ///</summary>
  485. public static float ToSingle(byte[] value, int startIndex)
  486. {
  487. if (IsLittleEndian)
  488. {
  489. return System.BitConverter.ToSingle(value, startIndex);
  490. }
  491. else
  492. {
  493. return System.BitConverter.ToSingle(value.Reverse().ToArray(), value.Length - sizeof(Single) - startIndex);
  494. }
  495. }
  496. ///
  497. /// <summary>
  498. /// Converts the numeric value of each element of a specified array of bytes
  499. /// to its equivalent hexadecimal string representation.
  500. ///
  501. /// Parameters:
  502. /// value:
  503. /// An array of bytes.
  504. ///
  505. /// Returns:
  506. /// A System.String of hexadecimal pairs separated by hyphens, where each pair
  507. /// represents the corresponding element in value; for example, "7F-2C-4A".
  508. ///
  509. /// Exceptions:
  510. /// System.ArgumentNullException:
  511. /// value is null.
  512. ///</summary>
  513. public static string ToString(byte[] value)
  514. {
  515. if (IsLittleEndian)
  516. {
  517. return System.BitConverter.ToString(value);
  518. }
  519. else
  520. {
  521. return System.BitConverter.ToString(value.Reverse().ToArray());
  522. }
  523. }
  524. ///
  525. /// <summary>
  526. /// Converts the numeric value of each element of a specified subarray of bytes
  527. /// to its equivalent hexadecimal string representation.
  528. ///
  529. /// Parameters:
  530. /// value:
  531. /// An array of bytes.
  532. ///
  533. /// startIndex:
  534. /// The starting position within value.
  535. ///
  536. /// Returns:
  537. /// A System.String of hexadecimal pairs separated by hyphens, where each pair
  538. /// represents the corresponding element in a subarray of value; for example,
  539. /// "7F-2C-4A".
  540. ///
  541. /// Exceptions:
  542. /// System.ArgumentNullException:
  543. /// value is null.
  544. ///
  545. /// System.ArgumentOutOfRangeException:
  546. /// startIndex is less than zero or greater than the length of value minus 1.
  547. ///</summary>
  548. public static string ToString(byte[] value, int startIndex)
  549. {
  550. if (IsLittleEndian)
  551. {
  552. return System.BitConverter.ToString(value, startIndex);
  553. }
  554. else
  555. {
  556. return System.BitConverter.ToString(value.Reverse().ToArray(), startIndex);
  557. }
  558. }
  559. ///
  560. /// <summary>
  561. /// Converts the numeric value of each element of a specified subarray of bytes
  562. /// to its equivalent hexadecimal string representation.
  563. ///
  564. /// Parameters:
  565. /// value:
  566. /// An array of bytes.
  567. ///
  568. /// startIndex:
  569. /// The starting position within value.
  570. ///
  571. /// length:
  572. /// The number of array elements in value to convert.
  573. ///
  574. /// Returns:
  575. /// A System.String of hexadecimal pairs separated by hyphens, where each pair
  576. /// represents the corresponding element in a subarray of value; for example,
  577. /// "7F-2C-4A".
  578. ///
  579. /// Exceptions:
  580. /// System.ArgumentNullException:
  581. /// value is null.
  582. ///
  583. /// System.ArgumentOutOfRangeException:
  584. /// startIndex or length is less than zero. -or- startIndex is greater than
  585. /// zero and is greater than or equal to the length of value.
  586. ///
  587. /// System.ArgumentException:
  588. /// The combination of startIndex and length does not specify a position within
  589. /// value; that is, the startIndex parameter is greater than the length of value
  590. /// minus the length parameter.
  591. ///</summary>
  592. public static string ToString(byte[] value, int startIndex, int length)
  593. {
  594. if (IsLittleEndian)
  595. {
  596. return System.BitConverter.ToString(value, startIndex, length);
  597. }
  598. else
  599. {
  600. return System.BitConverter.ToString(value.Reverse().ToArray(), startIndex, length);
  601. }
  602. }
  603. ///
  604. /// <summary>
  605. /// Returns a 16-bit unsigned integer converted from two bytes at a specified
  606. /// position in a byte array.
  607. ///
  608. /// Parameters:
  609. /// value:
  610. /// The array of bytes.
  611. ///
  612. /// startIndex:
  613. /// The starting position within value.
  614. ///
  615. /// Returns:
  616. /// A 16-bit unsigned integer formed by two bytes beginning at startIndex.
  617. ///
  618. /// Exceptions:
  619. /// System.ArgumentException:
  620. /// startIndex equals the length of value minus 1.
  621. ///
  622. /// System.ArgumentNullException:
  623. /// value is null.
  624. ///
  625. /// System.ArgumentOutOfRangeException:
  626. /// startIndex is less than zero or greater than the length of value minus 1.
  627. ///</summary>
  628. public static ushort ToUInt16(byte[] value, int startIndex)
  629. {
  630. if (IsLittleEndian)
  631. {
  632. return System.BitConverter.ToUInt16(value, startIndex);
  633. }
  634. else
  635. {
  636. return System.BitConverter.ToUInt16(value.Reverse().ToArray(), value.Length - sizeof(UInt16) - startIndex);
  637. }
  638. }
  639. ///
  640. /// <summary>
  641. /// Returns a 32-bit unsigned integer converted from four bytes at a specified
  642. /// position in a byte array.
  643. ///
  644. /// Parameters:
  645. /// value:
  646. /// An array of bytes.
  647. ///
  648. /// startIndex:
  649. /// The starting position within value.
  650. ///
  651. /// Returns:
  652. /// A 32-bit unsigned integer formed by four bytes beginning at startIndex.
  653. ///
  654. /// Exceptions:
  655. /// System.ArgumentException:
  656. /// startIndex is greater than or equal to the length of value minus 3, and is
  657. /// less than or equal to the length of value minus 1.
  658. ///
  659. /// System.ArgumentNullException:
  660. /// value is null.
  661. ///
  662. /// System.ArgumentOutOfRangeException:
  663. /// startIndex is less than zero or greater than the length of value minus 1.
  664. ///</summary>
  665. public static uint ToUInt32(byte[] value, int startIndex)
  666. {
  667. if (IsLittleEndian)
  668. {
  669. return System.BitConverter.ToUInt32(value, startIndex);
  670. }
  671. else
  672. {
  673. return System.BitConverter.ToUInt32(value.Reverse().ToArray(), value.Length - sizeof(UInt32) - startIndex);
  674. }
  675. }
  676. ///
  677. /// <summary>
  678. /// Returns a 64-bit unsigned integer converted from eight bytes at a specified
  679. /// position in a byte array.
  680. ///
  681. /// Parameters:
  682. /// value:
  683. /// An array of bytes.
  684. ///
  685. /// startIndex:
  686. /// The starting position within value.
  687. ///
  688. /// Returns:
  689. /// A 64-bit unsigned integer formed by the eight bytes beginning at startIndex.
  690. ///
  691. /// Exceptions:
  692. /// System.ArgumentException:
  693. /// startIndex is greater than or equal to the length of value minus 7, and is
  694. /// less than or equal to the length of value minus 1.
  695. ///
  696. /// System.ArgumentNullException:
  697. /// value is null.
  698. ///
  699. /// System.ArgumentOutOfRangeException:
  700. /// startIndex is less than zero or greater than the length of value minus 1.
  701. ///</summary>
  702. public static ulong ToUInt64(byte[] value, int startIndex)
  703. {
  704. if (IsLittleEndian)
  705. {
  706. return System.BitConverter.ToUInt64(value, startIndex);
  707. }
  708. else
  709. {
  710. return System.BitConverter.ToUInt64(value.Reverse().ToArray(), value.Length - sizeof(UInt64) - startIndex);
  711. }
  712. }
  713. }
  714. }

URL: http://msdn.microsoft.com/en-us/library/system.bitconverter.aspx

Report this snippet


Comments

RSS Icon Subscribe to comments

You need to login to post a comment.